Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug 1640575 - Move "debug view tagging" to Rust #998

Merged
merged 5 commits into from
Jun 25, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -585,6 +585,21 @@ open class GleanInternalAPI internal constructor () {
}
}

/**
* Set a tag to be applied to headers when uploading pings for debug view.
* This is only meant to be used internally by the `GleanDebugActivity`.
*
* @param value The value of the tag, which must be a valid HTTP header value.
*/
fun setDebugViewTag(value: String): Boolean {
if (isInitialized()) {
brizental marked this conversation as resolved.
Show resolved Hide resolved
return LibGleanFFI.INSTANCE.glean_set_debug_view_tag(value).toBoolean()
} else {
Log.e(LOG_TAG, "Glean must be initialized before setting a debug view tag.")
return false
}
}

/**
* TEST ONLY FUNCTION.
* This is called by the GleanTestRule, to enable test mode.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,6 @@ internal class FfiConfiguration(
* @property logPings whether to log ping contents to the console. This is only meant to be used
* internally by the `GleanDebugActivity`.
* @property httpClient The HTTP client implementation to use for uploading pings.
* @property pingTag String tag to be applied to headers when uploading pings for debug view.
* This is only meant to be used internally by the `GleanDebugActivity`.
* @property channel the release channel the application is on, if known. This will be
* sent along with all the pings, in the `client_info` section.
*/
Expand All @@ -68,8 +66,7 @@ data class Configuration internal constructor(
// NOTE: since only simple object or strings can be made `const val`s, if the
// default values for the lines below are ever changed, they are required
// to change in the public constructor below.
val httpClient: PingUploader = HttpURLConnectionUploader(),
val pingTag: String? = null
val httpClient: PingUploader = HttpURLConnectionUploader()
) {
/**
* Configuration for Glean.
Expand Down Expand Up @@ -97,7 +94,6 @@ data class Configuration internal constructor(
maxEvents = maxEvents,
logPings = DEFAULT_LOG_PINGS,
httpClient = httpClient,
pingTag = null,
channel = channel
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,6 @@ class GleanDebugActivity : Activity() {
* The value must match the pattern `[a-zA-Z0-9-]{1,20}`.
*/
const val TAG_DEBUG_VIEW_EXTRA_KEY = "tagPings"

// Regular expression filter for debugId
internal val pingTagPattern = "[a-zA-Z0-9-]{1,20}".toRegex()
}

// IMPORTANT: These activities are unsecured, and may be triggered by
Expand Down Expand Up @@ -83,19 +80,15 @@ class GleanDebugActivity : Activity() {

// Check for ping debug view tag to apply to the X-Debug-ID header when uploading the
// ping to the endpoint
var pingTag: String? = intent.getStringExtra(TAG_DEBUG_VIEW_EXTRA_KEY)
var debugViewTag: String? = intent.getStringExtra(TAG_DEBUG_VIEW_EXTRA_KEY)

// Validate the ping tag against the regex pattern
pingTag?.let {
if (!pingTagPattern.matches(it)) {
Log.e(LOG_TAG, "tagPings value $it does not match accepted pattern $pingTagPattern")
pingTag = null
}
// Set the debug view tag, if the tag is invalid it won't be set
debugViewTag?.let {
Glean.setDebugViewTag(debugViewTag)
brizental marked this conversation as resolved.
Show resolved Hide resolved
}

val debugConfig = Glean.configuration.copy(
logPings = intent.getBooleanExtra(LOG_PINGS_EXTRA_KEY, Glean.configuration.logPings),
pingTag = pingTag
logPings = intent.getBooleanExtra(LOG_PINGS_EXTRA_KEY, Glean.configuration.logPings)
)

// Finally set the default configuration before starting
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import org.json.JSONException
import com.sun.jna.Structure
import com.sun.jna.Pointer
import com.sun.jna.Union
import mozilla.telemetry.glean.Glean
import mozilla.telemetry.glean.rust.getRustString
import mozilla.telemetry.glean.rust.RustBuffer

Expand Down Expand Up @@ -93,10 +92,6 @@ internal class PingRequest(
Log.e(LOG_TAG, "Error while parsing headers for ping $documentId")
}

Glean.configuration.pingTag?.let {
headers.add(Pair("X-Debug-ID", it))
}

return headers
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -560,6 +560,8 @@ internal interface LibGleanFFI : Library {

fun glean_process_ping_upload_response(task: FfiPingUploadTask.ByReference, status: Int)

fun glean_set_debug_view_tag(value: String): Byte

// Misc

fun glean_str_free(ptr: Pointer)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,14 +104,14 @@ class GleanTest {
}

@Test
fun `X-Debug-ID header is correctly added when pingTag is not null`() {
fun `X-Debug-ID header is correctly added when debug view tag is set`() {
brizental marked this conversation as resolved.
Show resolved Hide resolved
val server = getMockWebServer()
resetGlean(context, Glean.configuration.copy(
serverEndpoint = "http://" + server.hostName + ":" + server.port,
logPings = true,
pingTag = "this-ping-is-tagged"
logPings = true
))

Glean.setDebugViewTag("this-ping-is-tagged")
Glean.handleBackgroundEvent()

// Now trigger it to upload
Expand Down
2 changes: 2 additions & 0 deletions glean-core/ffi/glean.h
Original file line number Diff line number Diff line change
Expand Up @@ -642,6 +642,8 @@ uint8_t glean_quantity_test_has_value(uint64_t metric_id, FfiStr storage_name);

void glean_register_ping_type(uint64_t ping_type_handle);

uint8_t glean_set_debug_view_tag(FfiStr tag);

void glean_set_dirty_flag(uint8_t flag);

void glean_set_experiment_active(FfiStr experiment_id,
Expand Down
8 changes: 8 additions & 0 deletions glean-core/ffi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -492,4 +492,12 @@ pub extern "C" fn glean_initialize_standalone_uploader(data_dir: FfiStr) -> u8 {
})
}

#[no_mangle]
pub extern "C" fn glean_set_debug_view_tag(tag: FfiStr) -> u8 {
with_glean_mut(|glean| {
let tag = tag.to_string_fallible()?;
Ok(glean.set_debug_view_tag(&tag))
})
}

define_string_destructor!(glean_str_free);
6 changes: 0 additions & 6 deletions glean-core/ios/Glean/Config/Configuration.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ public struct Configuration {
let serverEndpoint: String
var logPings: Bool
let maxEvents: Int32?
var pingTag: String?
brizental marked this conversation as resolved.
Show resolved Hide resolved
let channel: String?

struct Constants {
Expand All @@ -24,21 +23,17 @@ public struct Configuration {
/// * logPings: whether to log ping contents to the console.
/// This is only meant to be used internally by the `GleanDebugActivity`.
/// * maxEvents: the number of events to store before the events ping is sent.
/// * pingTag: String tag to be applied to headers when uploading pings for debug view.
/// Used internally by the `GleanDebugActivity`.
/// * channel: the release channel the application is on, if known.
/// This will be sent along with all the pings, in the `client_info` section.
internal init(
serverEndpoint: String = Constants.defaultTelemetryEndpoint,
logPings: Bool = Constants.defaultLogPings,
maxEvents: Int32? = nil,
pingTag: String? = nil,
channel: String? = nil
) {
self.serverEndpoint = serverEndpoint
self.logPings = logPings
self.maxEvents = maxEvents
self.pingTag = pingTag
self.channel = channel
}

Expand All @@ -56,7 +51,6 @@ public struct Configuration {
self.serverEndpoint = serverEndpoint ?? Constants.defaultTelemetryEndpoint
self.logPings = Constants.defaultLogPings
self.maxEvents = maxEvents
self.pingTag = nil
self.channel = channel
}

Expand Down
17 changes: 6 additions & 11 deletions glean-core/ios/Glean/Debug/GleanDebugTools.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,6 @@ class GleanDebugUtility {
// This struct is used for organizational purposes to keep the class constants in a single place
struct Constants {
static let logTag = "glean/GleanDebugUtility"
// Since ping tags are transmitted via HTTP in a header, and since they are displayed to the
// user on the Glean Debug View, we need to constrain the tag to a safe character set and
// limit the length to prevent possible attack vectors.
static let pingTagRegexPattern = "^[a-zA-Z0-9-]{1,20}$"
}

private static let logger = Logger(tag: Constants.logTag)
Expand Down Expand Up @@ -58,8 +54,12 @@ class GleanDebugUtility {

if let parsedCommands = processCustomUrlQuery(urlQueryItems: params) {
if let tag = parsedCommands.pingTag {
Glean.shared.configuration?.pingTag = tag
logger.debug("Pings tagged with: \(tag)")
if Glean.shared.setDebugViewTag(tag) {
logger.debug("Pings tagged with: \(tag)")
} else {
logger.error("Invalid ping tag name, aborting Glean debug tools")
return
}
}

if let logPings = parsedCommands.logPings {
Expand Down Expand Up @@ -107,11 +107,6 @@ class GleanDebugUtility {
return nil
}

if !param.value!.matches(Constants.pingTagRegexPattern) {
logger.error("Invalid ping tag name, aborting Glean debug tools")
return nil
}

pingTagName = param.value
case "logPings":
if willLogPings != nil {
Expand Down
14 changes: 14 additions & 0 deletions glean-core/ios/Glean/Glean.swift
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,20 @@ public class Glean {
}
}

/// Set a tag to be applied to headers when uploading pings for debug view.
/// This is only meant to be used internally by the `GleanDebugActivity`.
///
/// - parameters:
/// * value: The value of the tag, which must be a valid HTTP header value.
public func setDebugViewTag(_ value: String) -> Bool {
if self.isInitialized() {
return glean_set_debug_view_tag(value).toBool()
} else {
self.logger.error("Glean must be initialized before setting a debug view tag.")
return false
}
}

/// When applications are launched using the custom URL scheme, this helper function will process
/// the URL and parse the debug commands
///
Expand Down
2 changes: 2 additions & 0 deletions glean-core/ios/Glean/GleanFfi.h
Original file line number Diff line number Diff line change
Expand Up @@ -642,6 +642,8 @@ uint8_t glean_quantity_test_has_value(uint64_t metric_id, FfiStr storage_name);

void glean_register_ping_type(uint64_t ping_type_handle);

uint8_t glean_set_debug_view_tag(FfiStr tag);

void glean_set_dirty_flag(uint8_t flag);

void glean_set_experiment_active(FfiStr experiment_id,
Expand Down
4 changes: 0 additions & 4 deletions glean-core/ios/Glean/Net/HttpPingUploader.swift
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,6 @@ public class HttpPingUploader {
// See https://github.com/AliSoftware/OHHTTPStubs#known-limitations.
request.httpBody = data

if let tag = config.pingTag {
request.addValue(tag, forHTTPHeaderField: "X-Debug-ID")
}

return request
}

Expand Down
6 changes: 0 additions & 6 deletions glean-core/ios/Glean/Net/Upload.swift
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,6 @@ struct PingRequest {
self.documentId = documentId
self.path = path
self.body = body

var headers = headers
if let pingTag = Glean.shared.configuration?.pingTag {
headers["X-Debug-ID"] = pingTag
}

self.headers = headers
}
}
Expand Down
4 changes: 0 additions & 4 deletions glean-core/ios/GleanTests/Config/ConfigurationTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,6 @@ class ConfigurationTests: XCTestCase {
config?.maxEvents,
"Default max events are set"
)
XCTAssertNil(
config?.pingTag,
"Default pingTag is set"
)
XCTAssertNil(
config?.channel,
"Default channel is set"
Expand Down
19 changes: 0 additions & 19 deletions glean-core/ios/GleanTests/Debug/GleanDebugUtilityTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,25 +19,6 @@ class GleanDebugUtilityTests: XCTestCase {
OHHTTPStubs.removeAllStubs()
}

func testHandleCustomUrlTagPings() {
// Check invalid tags: This should have the configuration keep the
// default value of nil because they don't match the accepted
// regex for ping tag names.
var url = URL(string: "test://glean?tagPings=This-tag-is-not-valid-because-it-is-too-long")
Glean.shared.handleCustomUrl(url: url!)
XCTAssertNil(Glean.shared.configuration?.pingTag)

url = URL(string: "test://glean?tagPings=Invalid_Chars@!!$")
Glean.shared.handleCustomUrl(url: url!)
XCTAssertNil(Glean.shared.configuration?.pingTag)

// Check valid tag: This should update the pingTag value of the
// configuration object.
url = URL(string: "test://glean?tagPings=Glean-Ping")
Glean.shared.handleCustomUrl(url: url!)
XCTAssertEqual("Glean-Ping", Glean.shared.configuration?.pingTag)
}

func testHandleCustomUrlLogPings() {
// Test initial state
XCTAssertFalse(Glean.shared.configuration!.logPings)
Expand Down
3 changes: 1 addition & 2 deletions glean-core/ios/GleanTests/Net/HttpPingUploaderTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@ class HttpPingUploaderTests: XCTestCase {
private let testPath = "/some/random/path/not/important"
private let testPing = "{ \"ping\": \"test\" }"
private let testConfig = Configuration(
logPings: true,
pingTag: "Tag"
logPings: true
)

override func tearDown() {
Expand Down
Loading