Handle interfaces with a ServiceName in the go bindings generator.

R=vardhan@google.com, vardhan

Review URL: https://codereview.chromium.org/2077113002 .
diff --git a/mojom/generators/go/templates/interfaces.go b/mojom/generators/go/templates/interfaces.go
index ed95d5f..4634650 100644
--- a/mojom/generators/go/templates/interfaces.go
+++ b/mojom/generators/go/templates/interfaces.go
@@ -12,6 +12,14 @@
 {{- define "Interface" -}}
 {{$interface := . -}}
 {{ template "InterfaceDecl" $interface }}
+
+{{- range $method := $interface.Methods -}}
+{{ template "Method" $method }}
+{{- end -}}
+
+{{- if $interface.ServiceName -}}
+{{ template "ServiceDecl" $interface }}
+{{- end -}}
 {{- end -}}
 `
 
@@ -87,6 +95,18 @@
 {{- end -}}
 `
 
+const methodTmplText = `
+{{- define "Method" -}}
+{{- $method := . -}}
+
+{{ template "MethodParams" $method }}
+
+{{ template "MethodSignature" $method }}
+
+{{ template "MethodFunction" $method }}
+{{- end -}}
+`
+
 const methodOrdinalsTmplText = `
 {{- define "MethodOrdinals" -}}
 {{- $interface := . -}}
@@ -184,12 +204,34 @@
 {{- end -}}
 `
 
+const serviceDeclTmplText = `
+{{- define "ServiceDecl" -}}
+{{- $interface := . -}}
+const {{$interface.PrivateName}}_Name string = "{{$interface.ServiceName}}"
+
+func (r *{{$interface.Name}}_Request) Name() string {
+	return {{$interface.PrivateName}}_Name
+}
+
+func (p *{{$interface.Name}}_Pointer) Name() string {
+	return {{$interface.PrivateName}}_Name
+}
+
+func (f *{{$interface.Name}}_ServiceFactory) Name() string {
+	return {{$interface.PrivateName}}_Name
+}
+{{- end -}}
+`
+
 func initInterfaceTemplates() {
+	template.Must(goFileTmpl.Parse(interfaceTmplText))
 	template.Must(goFileTmpl.Parse(interfaceDeclTmplText))
 	template.Must(goFileTmpl.Parse(interfaceInterfaceDeclTmplText))
 	template.Must(goFileTmpl.Parse(interfaceOtherDeclTmplText))
+	template.Must(goFileTmpl.Parse(serviceDeclTmplText))
 	template.Must(goFileTmpl.Parse(methodOrdinalsTmplText))
 	template.Must(goFileTmpl.Parse(methodParamsTmplText))
 	template.Must(goFileTmpl.Parse(methodSignatureTmplText))
 	template.Must(goFileTmpl.Parse(methodFuncTmplText))
+	template.Must(goFileTmpl.Parse(methodTmplText))
 }
diff --git a/mojom/generators/go/templates/interfaces_test.go b/mojom/generators/go/templates/interfaces_test.go
index 684749a..aa2893e 100644
--- a/mojom/generators/go/templates/interfaces_test.go
+++ b/mojom/generators/go/templates/interfaces_test.go
@@ -64,3 +64,28 @@
 
 	check(t, expected, "MethodOrdinals", i)
 }
+
+func TestServiceName(t *testing.T) {
+	expected := `const someInterface_Name string = "SomeService"
+
+func (r *SomeInterface_Request) Name() string {
+	return someInterface_Name
+}
+
+func (p *SomeInterface_Pointer) Name() string {
+	return someInterface_Name
+}
+
+func (f *SomeInterface_ServiceFactory) Name() string {
+	return someInterface_Name
+}`
+
+	serviceName := "SomeService"
+	i := translator.InterfaceTemplate{
+		Name:        "SomeInterface",
+		PrivateName: "someInterface",
+		ServiceName: &serviceName,
+	}
+
+	check(t, expected, "ServiceDecl", i)
+}
diff --git a/mojom/generators/go/templates/templates.go b/mojom/generators/go/templates/templates.go
index 40973b3..4d6a945 100644
--- a/mojom/generators/go/templates/templates.go
+++ b/mojom/generators/go/templates/templates.go
@@ -67,5 +67,9 @@
 {{- range $enum := $fileTmpl.Enums}}
 	{{ template "Enum" $enum }}
 {{- end}}
+
+{{- range $interface := $fileTmpl.Interfaces}}
+	{{ template "Interface" $interface }}
+{{- end}}
 {{- end -}}
 `
diff --git a/mojom/generators/go/translator/mojom_file.go b/mojom/generators/go/translator/mojom_file.go
index efc05fa..2ba381c 100644
--- a/mojom/generators/go/translator/mojom_file.go
+++ b/mojom/generators/go/translator/mojom_file.go
@@ -12,6 +12,7 @@
 	Structs     []*StructTemplate
 	Unions      []*UnionTemplate
 	Enums       []*EnumTemplate
+	Interfaces  []*InterfaceTemplate
 }
 
 type Import struct {
@@ -125,6 +126,9 @@
 	// PrivateName is identical to Name with the first letter lower cased.
 	PrivateName string
 
+	// ServiceName is the service name of the interface.
+	ServiceName *string
+
 	// Methods contains the list of methods of the interface.
 	Methods []MethodTemplate
 }
diff --git a/mojom/generators/go/translator/names.go b/mojom/generators/go/translator/names.go
index 5824841..f95849d 100644
--- a/mojom/generators/go/translator/names.go
+++ b/mojom/generators/go/translator/names.go
@@ -42,21 +42,25 @@
 	return base[:len(base)-len(ext)]
 }
 
-// userDefinedTypeShortName extracts the ShortName from a user-defined type.
-func userDefinedTypeShortName(userDefinedType mojom_types.UserDefinedType) string {
+func userDefinedTypeDeclData(userDefinedType mojom_types.UserDefinedType) *mojom_types.DeclarationData {
 	switch u := userDefinedType.(type) {
 	case *mojom_types.UserDefinedTypeEnumType:
-		return *u.Value.DeclData.ShortName
+		return u.Value.DeclData
 	case *mojom_types.UserDefinedTypeStructType:
-		return *u.Value.DeclData.ShortName
+		return u.Value.DeclData
 	case *mojom_types.UserDefinedTypeUnionType:
-		return *u.Value.DeclData.ShortName
+		return u.Value.DeclData
 	case *mojom_types.UserDefinedTypeInterfaceType:
-		return *u.Value.DeclData.ShortName
+		return u.Value.DeclData
 	}
 	panic("Non-handled mojom UserDefinedType. This should never happen.")
 }
 
+// userDefinedTypeShortName extracts the ShortName from a user-defined type.
+func userDefinedTypeShortName(userDefinedType mojom_types.UserDefinedType) string {
+	return *userDefinedTypeDeclData(userDefinedType).ShortName
+}
+
 // privateName accepts a string and returns that same string with the first rune
 // set to lowercase.
 func privateName(name string) string {
diff --git a/mojom/generators/go/translator/translator.go b/mojom/generators/go/translator/translator.go
index f71708d..96ad8b0 100644
--- a/mojom/generators/go/translator/translator.go
+++ b/mojom/generators/go/translator/translator.go
@@ -57,6 +57,11 @@
 		tmplFile.Enums[i+topLevelEnumsNum] = t.translateMojomEnum(typeKey)
 	}
 
+	tmplFile.Interfaces = make([]*InterfaceTemplate, len(*file.DeclaredMojomObjects.Interfaces))
+	for i, typeKey := range *file.DeclaredMojomObjects.Interfaces {
+		tmplFile.Interfaces[i] = t.translateMojomInterface(typeKey)
+	}
+
 	tmplFile.Imports = []Import{
 		Import{PackagePath: "mojo/public/go/bindings", PackageName: "bindings"},
 		Import{PackagePath: "fmt", PackageName: "fmt"},
@@ -173,6 +178,7 @@
 
 	m.Name = t.goTypeName(typeKey)
 	m.PrivateName = privateName(m.Name)
+	m.ServiceName = mojomInterface.ServiceName
 
 	for _, mojomMethod := range mojomInterface.Methods {
 		m.Methods = append(m.Methods, *t.translateMojomMethod(mojomMethod, m))
diff --git a/mojom/generators/go/translator/types.go b/mojom/generators/go/translator/types.go
index c76afe6..2b8390d 100644
--- a/mojom/generators/go/translator/types.go
+++ b/mojom/generators/go/translator/types.go
@@ -121,7 +121,18 @@
 }
 
 func (t *translator) translateTypeReference(typeRef mojom_types.TypeReference) (goType string) {
-	// TODO(azani): Handle interface requests.
 	// TOOD(azani): Handle imported types.
-	return t.goTypeName(*typeRef.TypeKey)
+	typeKey := *typeRef.TypeKey
+	userDefinedType := t.fileGraph.ResolvedTypes[typeKey]
+	typeName := t.goTypeName(*typeRef.TypeKey)
+
+	if _, ok := userDefinedType.(*mojom_types.UserDefinedTypeInterfaceType); ok {
+		if typeRef.IsInterfaceRequest {
+			return fmt.Sprintf("%s_Proxy", typeName)
+		} else {
+			return fmt.Sprintf("%s_Pointer", typeName)
+		}
+	}
+
+	return typeName
 }
diff --git a/mojom/generators/go/translator/types_test.go b/mojom/generators/go/translator/types_test.go
index c3f1c7e..0f18ed9 100644
--- a/mojom/generators/go/translator/types_test.go
+++ b/mojom/generators/go/translator/types_test.go
@@ -90,3 +90,38 @@
 	typeRef := &mojom_types.TypeTypeReference{mojom_types.TypeReference{TypeKey: &typeKey}}
 	checkEq(t, shortName, translator.translateType(typeRef))
 }
+
+func TestTranslateInterfaceType(t *testing.T) {
+	fileGraph := mojom_files.MojomFileGraph{}
+	shortName := "FooBar"
+	typeKey := "typeKey"
+	i := mojom_types.MojomInterface{
+		DeclData: &mojom_types.DeclarationData{ShortName: &shortName},
+	}
+	fileGraph.ResolvedTypes = map[string]mojom_types.UserDefinedType{}
+	fileGraph.ResolvedTypes[typeKey] = &mojom_types.UserDefinedTypeInterfaceType{i}
+
+	typeRef := &mojom_types.TypeTypeReference{mojom_types.TypeReference{TypeKey: &typeKey}}
+
+	translator := NewTranslator(&fileGraph)
+	checkEq(t, "FooBar_Pointer", translator.translateType(typeRef))
+}
+
+func TestTranslateInterfaceRequestType(t *testing.T) {
+	fileGraph := mojom_files.MojomFileGraph{}
+	shortName := "FooBar"
+	typeKey := "typeKey"
+	i := mojom_types.MojomInterface{
+		DeclData: &mojom_types.DeclarationData{ShortName: &shortName},
+	}
+	fileGraph.ResolvedTypes = map[string]mojom_types.UserDefinedType{}
+	fileGraph.ResolvedTypes[typeKey] = &mojom_types.UserDefinedTypeInterfaceType{i}
+
+	typeRef := &mojom_types.TypeTypeReference{mojom_types.TypeReference{
+		TypeKey:            &typeKey,
+		IsInterfaceRequest: true,
+	}}
+
+	translator := NewTranslator(&fileGraph)
+	checkEq(t, "FooBar_Proxy", translator.translateType(typeRef))
+}