DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Git (975a35c0f5)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138
###############################################################################
# Global configurations.  Protip: set your own overrides in a local.mk file.  #
#                                                                             #
# SYSTEM      : url of the SYSTEM to start on                                 #
#                                                                             #
# ADB         : if you use a device and plan to send update it with your work #
#               you need to have adb in your path or you can edit this line to#
#               specify its location.                                         #
#                                                                             #
# DEBUG       : debug mode enables mode output on the console and disable the #
#               the offline cache. This is mostly for desktop debugging.      #
#                                                                             #
# REPORTER    : Mocha reporter to use for test output.                        #
#                                                                             #
# MARIONETTE_RUNNER_HOST : ie marionette-device-host                          #
#                                                                             #
# COVERAGE    : Add blanket testing coverage report to use for test output.   #
#                                                                             #
# GAIA_APP_CONFIG : The app.list file representing applications to include in #
#                   Gaia                                                      #
#                                                                             #
###############################################################################
#                                                                             #
# Lint your code                                                              #
#                                                                             #
# Use "make lint" to lint using jshint                                        #
#                                                                             #
# Use "make eslint" to lint using eslint. This is currently used for checks   #
# that are beyond the other linter's scope, i.e., customized checks for       #
# discouraged coding patterns or deprecated APIs.                             #
#                                                                             #
# APP=<app name> will hint/lint only this app.                                #
# LINTED_FILES=<list of files> will (h/l)int only these space-separated files #
# JSHINTRC=<path> will use this config file when running jshint               #
#                                                                             #
###############################################################################
#                                                                             #
# b2g desktop download and location configuration (formerly xulrunner)        #
#                                                                             #
# USE_LOCAL_XULRUNNER_SDK  : if you have a local b2g desktop installation     #
#                            and want to use it                               #
#                                                                             #
# XULRUNNER_DIRECTORY      : if you use USE_LOCAL_XULRUNNER_SDK, this is      #
#                            where your local b2g desktop installation is     #
#                            Note: a full firefox build is good enough        #
#                                                                             #
# Submakes will get XULRUNNER_DIRECTORY and XPCSHELLSDK as absolute paths.    #
#                                                                             #
###############################################################################


# Eliminate use of the built-in implicit rules to get faster.
MAKEFLAGS=-r

# Rebuild when user specifying these config. If following config are specified,
# build system considers it will load exteranl resources and force rebuilding.
REBUILD?=0
ifdef GAIA_DISTRIBUTION_DIR
	REBUILD=1
endif
ifdef LOCALE_BASEDIR
	REBUILD=1
endif
ifdef LOCALES_FILE
	REBUILD=1
endif

RUN_ON_NODE?=0

ifeq ($(RUN_ON_NODE),0)
BUILD_RUNNER=run-js-command
else
BUILD_RUNNER=run-node-command
endif

-include local.mk

# Headless bot does not need the full output of wget
# and it can cause crashes in bot.io option is here so
# -nv can be passed and turn off verbose output.
WGET_OPTS?=-c -nv

DEBUG?=0
DEVICE_DEBUG?=0
NO_LOCK_SCREEN?=0
SCREEN_TIMEOUT?=-1
PRODUCTION?=0
GAIA_OPTIMIZE?=0
GAIA_DEV_PIXELS_PER_PX?=1
NGA_SERVICE_WORKERS?=0

# Parallel build for multicores CPU
P?=1

# Alias
ifdef GAIA_DPPX
GAIA_DEV_PIXELS_PER_PX=$(GAIA_DPPX)
endif

DOGFOOD?=0
NODE_MODULES_SRC?=modules.tar
NODE_MODULES_CACHEDIR=modules_tar_cachedir

# GAIA_DEVICE_TYPE customization
# phone - default
# tablet
# tv
GAIA_DEVICE_TYPE?=phone
-include build/config/$(GAIA_DEVICE_TYPE)/device.mk

TEST_AGENT_PORT?=8789
GAIA_APP_TARGET?=engineering

# Enable compatibility to run in Firefox Desktop
DESKTOP?=$(DEBUG)
# Disable first time experience screen
NOFTU?=1
# Disable first time ping
NOFTUPING?=1
# Automatically enable remote debugger
REMOTE_DEBUGGER?=0
# Debug mode for build process
BUILD_DEBUG?=0

# Enable PerformanceTiming logs
PERF_LOGGING?=0

# Are we building for RAPTOR?
RAPTOR?=0

# Enable hardware composing by default
HARDWARE_COMPOSER?=1

# Share performance and usage data
SHARE_PERF_USAGE?=1

# what version of node we expect to run for ideal support.
NODE_VERSION=v4.2
# the minimum major version is absolutely required.
NODE_MIN_VERSION=4

# what version of npm we expect to run for ideal support.
NPM_VERSION=2

ifeq ($(DEVICE_DEBUG),1)
REMOTE_DEBUGGER=1
NO_LOCK_SCREEN=1
SCREEN_TIMEOUT?=300
endif

# We also disable FTU when running in Firefox or in debug mode
ifeq ($(DEBUG),1)
NOFTU=1
NOFTUPING=1
PROFILE_FOLDER?=profile-debug
else ifeq ($(DESKTOP),1)
NOFTU=1
NOFTUPING=1
PROFILE_FOLDER?=profile-debug
else ifeq ($(MAKECMDGOALS),test-integration)
PROFILE_FOLDER?=profile-test
endif

ifeq ($(NOFTUPING), 0)
FTU_PING_URL?=https://fxos.telemetry.mozilla.org/submit/telemetry
else
$(warning NO_FTU_PING=1)
endif

PROFILE_FOLDER?=profile

STAGE_DIR?=$(GAIA_DIR)$(SEP)build_stage
export STAGE_DIR

ADB?=adb

SCHEME=chrome://gaia/content/

SYSTEM?=$(SCHEME)system

BUILD_APP_NAME?=*
ifneq ($(APP),)
ifneq ($(MAKECMDGOALS), test-integration)
BUILD_APP_NAME=$(APP)
endif
endif

# BUILDAPP variable defines the target b2g platform (eg desktop, device)
# and exports it for the gaia-marionette script
BUILDAPP?=desktop
export BUILDAPP
# Ensure that NPM only logs warnings and errors
export npm_config_loglevel=warn
ifneq ($(BUILDAPP),desktop)
REPORTER?=mocha-tbpl-reporter
endif
REPORTER?=spec
MARIONETTE_RUNNER_HOST?=marionette-b2gdesktop-host
TEST_MANIFEST?=$(shell pwd)/shared/test/integration/local-manifest.json

ifeq ($(MAKECMDGOALS), demo)
GAIA_APP_TARGET=demo
else ifeq ($(MAKECMDGOALS), dogfood)
DOGFOOD=1
else ifeq ($(MAKECMDGOALS), production)
PRODUCTION=1
endif

ifeq ($(DOGFOOD), 1)
PRODUCTION=1
endif

# PRODUCTION is also set for user and userdebug B2G builds
ifeq ($(PRODUCTION), 1)
GAIA_OPTIMIZE=1
GAIA_APP_TARGET=production
endif

ifeq ($(DOGFOOD), 1)
GAIA_APP_TARGET=dogfood
endif

ifdef NODE_MODULES_GIT_URL
NODE_MODULES_SRC := git-gaia-node-modules
endif

###############################################################################
# The above rules generate the profile/ folder and all its content.           #
# The profile folder content depends on different rules:                      #
#  1. webapp manifest                                                         #
#     A directory structure representing the applications installed using the #
#     Apps API. In Gaia all applications use this method.                     #
#     See https://developer.mozilla.org/en/Apps/Apps_JavaScript_API           #
#                                                                             #
#  2. offline                                                                 #
#     An Application Cache database containing Gaia apps, so the phone can be #
#     used offline and application can be updated easily. For details about it#
#     see: https://developer.mozilla.org/en/Using_Application_Cache           #
#                                                                             #
#  3. preferences                                                             #
#     A preference file used by the platform to configure permissions         #
#                                                                             #
###############################################################################

# In debug mode the offline cache is not used (even if it is generated) and
# Gaia is loaded by a built-in web server via port GAIA_PORT.
#
# XXX For now the name of the domain should be mapped to localhost manually
# by editing /etc/hosts on linux/mac. This steps would not be required
# anymore once https://bugzilla.mozilla.org/show_bug.cgi?id=722197 will land.
ifeq ($(DEBUG),1)
GAIA_PORT?=:8080
else
GAIA_PORT?=
endif

# Force bash for all shell commands since we depend on bash-specific syntax
SHELL := /bin/bash

GAIA_DIR := $(CURDIR)

# what OS are we on?
SYS=$(shell uname -s)
ARCH?=$(shell uname -m)
MSYS_FIX=
ifeq (${SYS}/${ARCH},Darwin/i386)
ARCH=x86_64
endif
SEP=/
SEP_FOR_SED=/
ifneq (,$(findstring MINGW32_,$(SYS)))
GAIA_DIR:=$(shell pwd -W | sed -e 's|/|\\\\|g')
SEP=\\
SEP_FOR_SED=\\\\
# Mingw mangle path and append c:\mozilla-build\msys\data in front of paths
MSYS_FIX=/
endif

# The b2g_sdk target arranges to get b2g desktop downloaded and set up.
# This is platform dependent code, so a mite complicated.
# Note: this used to be just xulrunner, hence the use of that name throughout,
# but xulrunner doesn't include everything we need

# Configuration for pre-built or already downloaded b2g (or alternative)
ifdef USE_LOCAL_XULRUNNER_SDK

ifndef XULRUNNER_DIRECTORY
$(error XULRUNNER_DIRECTORY must be set if USE_LOCAL_XULRUNNER_SDK is set)
endif

# Some guesswork to figure out where the xpcshell binary really is
# Most of this is to accommodate the variety of setups used
# by different platforms, build systems and TBPL configurations
# including Firefox, xulrunner and other builds
XPCSHELL_GUESS = $(firstword $(wildcard \
    $(XULRUNNER_DIRECTORY)/B2G.app/Contents/MacOS/xpcshell \
    $(XULRUNNER_DIRECTORY)/bin/XUL.framework/Versions/Current/xpcshell \
    $(XULRUNNER_DIRECTORY)/bin/xpcshell* \
    $(XULRUNNER_DIRECTORY)/b2g/xpcshell* \
  ))
ifneq (,$(XPCSHELL_GUESS))
XPCSHELLSDK := $(abspath $(XPCSHELL_GUESS))
XULRUNNERSDK := $(wildcard $(XPCSHELLSDK)/run-mozilla.sh)
endif

# Configuration for a downloaded b2g desktop
else

# Determine the host-dependent bundle to download
B2G_SDK_VERSION := 39.0a1
B2G_SDK_DATE := 2015/03/2015-03-05-16-02-02

XULRUNNER_BASE_DIR ?= b2g_sdk
XULRUNNER_DIRECTORY ?= $(XULRUNNER_BASE_DIR)/$(B2G_SDK_VERSION)-$(notdir $(B2G_SDK_DATE))
XULRUNNER_DIRECTORY := $(abspath $(XULRUNNER_DIRECTORY))

ifeq ($(SYS),Darwin)
B2G_SDK_EXT := dmg
B2G_SDK_OS := mac64
XPCSHELLSDK := $(abspath $(XULRUNNER_DIRECTORY)/B2G.app/Contents/MacOS/xpcshell)

else ifeq ($(findstring MINGW32,$(SYS)), MINGW32)
B2G_SDK_EXT := zip
B2G_SDK_OS := win32
XPCSHELLSDK := $(abspath $(XULRUNNER_DIRECTORY)/b2g/xpcshell.exe)

# Otherwise, assume linux
else
B2G_SDK_EXT := tar.bz2
ifeq ($(ARCH),x86_64)
B2G_SDK_OS := linux-x86_64
else
B2G_SDK_OS := linux-i686
endif
XPCSHELLSDK := $(abspath $(XULRUNNER_DIRECTORY)/b2g/xpcshell)
endif

B2G_SDK_URL_BASE := http://ftp.mozilla.org/pub/mozilla.org/b2g/nightly/$(B2G_SDK_DATE)-mozilla-central
B2G_SDK_FILE_NAME := b2g-$(B2G_SDK_VERSION).multi.$(B2G_SDK_OS).$(B2G_SDK_EXT)
B2G_SDK_URL := $(B2G_SDK_URL_BASE)/$(B2G_SDK_FILE_NAME)
B2G_SDK_URL_FILE := $(XULRUNNER_DIRECTORY)/.b2g.url

endif # Firefox build workaround

# XULRUNNERSDK used to be run-mozilla.sh, but some builds don't include it
# Without that, Linux needs to reference the directory containing libxul.so
ifeq (,$(XULRUNNERSDK)$(findstring Darwin,$(SYS))$(findstring MINGW32_,$(SYS)))
ifeq (,$(LD_LIBRARY_PATH))
XULRUNNERSDK := LD_LIBRARY_PATH="$(dir $(XPCSHELLSDK))"
else
XULRUNNERSDK := LD_LIBRARY_PATH="$(dir $(XPCSHELLSDK)):$(LD_LIBRARY_PATH)"
endif
endif

# It's difficult to figure out XULRUNNERSDK in subprocesses; it's complex and
# some builders may want to override our find logic (ex: TBPL).
# So let's export these variables to external processes.
export XULRUNNER_DIRECTORY XULRUNNERSDK XPCSHELLSDK
export SYS
export GAIA_DIR
export SEP
export SEP_FOR_SED

# Need to predefine XULRUNNERSDK, XPCSHELLSDK, GAIA_DIR
include build/common.mk

ifndef GAIA_APP_CONFIG
GAIA_APP_CONFIG=$(GAIA_DIR)$(SEP)build$(SEP)config$(SEP)$(GAIA_DEVICE_TYPE)$(SEP)apps-$(GAIA_APP_TARGET).list
endif

ifndef GAIA_DISTRIBUTION_DIR
  GAIA_DISTRIBUTION_DIR := $(GAIA_DIR)$(SEP)distribution
else
  ifneq (,$(findstring MINGW32_,$(SYS)))
    GAIA_DISTRIBUTION_DIR := $(shell pushd $(GAIA_DISTRIBUTION_DIR) > /dev/null; \
      pwd -W | sed 's|/|\\\\|g'; popd > /dev/null;)
  else
    GAIA_DISTRIBUTION_DIR := $(realpath $(GAIA_DISTRIBUTION_DIR))
  endif
endif
export GAIA_DISTRIBUTION_DIR

SETTINGS_PATH ?= build/config/custom-settings.json
KEYBOARD_LAYOUTS_PATH ?= build/config/keyboard-layouts.json
CONTACTS_IMPORT_SERVICES_PATH ?= build/config/communications_services.json
EMAIL_SERVICES_PATH ?=
DEFAULT_KEYBOAD_SYMBOLS_FONT ?= shared/style/keyboard_symbols/Keyboard-Symbols.ttf
DEFAULT_GAIA_ICONS_FONT ?= shared/elements/gaia-icons/fonts/gaia-icons.ttf

ifdef GAIA_DISTRIBUTION_DIR
  DISTRIBUTION_SETTINGS := $(GAIA_DISTRIBUTION_DIR)$(SEP)settings.json
  DISTRIBUTION_CONTACTS := $(GAIA_DISTRIBUTION_DIR)$(SEP)contacts.json
  DISTRIBUTION_APP_CONFIG := $(GAIA_DISTRIBUTION_DIR)$(SEP)apps.list
  DISTRIBUTION_VARIANT := $(GAIA_DISTRIBUTION_DIR)$(SEP)variant.json
  DISTRIBUTION_KEYBOARD_LAYOUTS := $(GAIA_DISTRIBUTION_DIR)$(SEP)keyboard-layouts.json
  DISTRIBUTION_CONTACTS_IMPORT_SERVICES := $(GAIA_DISTRIBUTION_DIR)$(SEP)communications_services.json
  ifneq ($(wildcard $(DISTRIBUTION_SETTINGS)),)
    SETTINGS_PATH := $(DISTRIBUTION_SETTINGS)
  endif
  ifneq ($(wildcard $(DISTRIBUTION_CONTACTS)),)
    CONTACTS_PATH := $(DISTRIBUTION_CONTACTS)
  endif
  ifneq ($(wildcard $(DISTRIBUTION_APP_CONFIG)),)
    GAIA_APP_CONFIG := $(DISTRIBUTION_APP_CONFIG)
  endif
  ifneq ($(wildcard $(DISTRIBUTION_VARIANT)),)
    VARIANT_PATH := $(DISTRIBUTION_VARIANT)
  endif
  ifneq ($(wildcard $(DISTRIBUTION_KEYBOARD_LAYOUTS)),)
    KEYBOARD_LAYOUTS_PATH := $(DISTRIBUTION_KEYBOARD_LAYOUTS)
  endif
  ifneq ($(wildcard $(DISTRIBUTION_CONTACTS_IMPORT_SERVICES)),)
    CONTACTS_IMPORT_SERVICES_PATH := $(DISTRIBUTION_CONTACTS_IMPORT_SERVICES)
  endif
  ifneq ($(wildcard $(DISTRIBUTION_EMAIL_SERVICES)),)
    EMAIL_SERVICES_PATH := $(DISTRIBUTION_EMAIL_SERVICES)
  endif

  -include $(GAIA_DISTRIBUTION_DIR)$(SEP)distro.mk
endif

# Read the file specified in $GAIA_APP_CONFIG and turn them into $GAIA_APPDIRS,
# i.e., absolute path of each app.
# Path ending in wildcard (*) will be expanded, non-absolute path in the list will be matched against
# $GAIA_DISTRIBUTION_DIR and $GAIA_DIR.
# See MDN for more information.
#
# explain shell magic here:
# "$${LINE\#$${LINE%?}}": get last character
# sed 's/.\{2\}$$//': remove last two character

ifdef GAIA_APP_SRCDIRS
$(shell printf "`echo $(GAIA_APP_SRCDIRS) | sed 's| |/*\\\n|g'`/*\n" > /tmp/gaia-apps-temp.list)
GAIA_APP_CONFIG := /tmp/gaia-apps-temp.list
$(warning GAIA_APP_SRCDIRS is deprecated, please use GAIA_APP_CONFIG)
endif

GAIA_ALLAPPDIRS=$(shell find -L $(GAIA_DIR)$(SEP)apps $(GAIA_DIR)$(SEP)dev_apps $(GAIA_DIR)$(SEP)tv_apps -maxdepth 1 -mindepth 1 -type d  | sed 's@[/\\]@$(SEP_FOR_SED)@g')

# XXX: Using run-node-command would cause a circular reference error, but
# attempts to move the scan-appdir action to js (app.js) caused a strange issue
# with spawnProcess for xpcshell (unable to pass GAIA_APPDIRS in the options).
# Also need to make sure it runs xpcshell if RUN_ON_NODE is not turned on
# because b2g-inbound still runs node 0.10 rather than 4.x, and will break
# when parsing arrow function.
ifeq ($(RUN_ON_NODE),0)
	APPDIRS_BUILD_RUNNER=run-js-command
else
	APPDIRS_BUILD_RUNNER=run-node-command-without-config
endif

GAIA_APPDIRS?=$(shell $(call $(APPDIRS_BUILD_RUNNER),scan-appdir, \
		GAIA_APP_CONFIG="$(GAIA_APP_CONFIG)" \
		GAIA_DIR="$(GAIA_DIR)" \
		GAIA_DISTRIBUTION_DIR="$(GAIA_DISTRIBUTION_DIR)" \
		GAIA_APP_SRCDIRS="$(GAIA_APP_SRCDIRS)"))


ifneq ($(GAIA_OUTOFTREE_APP_SRCDIRS),)
  $(shell mkdir -p outoftree_apps \
    $(foreach dir,$(GAIA_OUTOFTREE_APP_SRCDIRS),\
      $(foreach appdir,$(wildcard $(dir)/*),\
	&& ln -sf $(appdir) outoftree_apps/)))
endif

GAIA_LOCALES_PATH?=locales
LOCALES_FILE?=shared/resources/languages.json
GAIA_LOCALE_SRCDIRS=$(GAIA_DIR)$(SEP)shared $(GAIA_APPDIRS)
GAIA_DEFAULT_LOCALE?=en-US
GAIA_PRETRANSLATE?=1
GAIA_CONCAT_LOCALES?=1

# This variable is for customizing the keyboard layouts in a build.
# Include the ID of the layout in this variable will make both the dictionary
# and the layout included in the package.
GAIA_KEYBOARD_LAYOUTS?=en,emoji,pt-BR,es,de,fr,fr-CA,pl,ko,zh-Hans-Pinyin,en-Dvorak
# We optionally offers downloading the dictionary from the CDN, instead of
# including it in the build.
# Include the ID of the layout in this variable will make it appear in the
# keyboard settings page, allowing user to download the dictionary.
# Any layout listed here that doesn't require a dictionary download and/or
# comes with its own dictionary will become a pre-installed layout,
# behaving the same way as if it is listed in the above variable.
GAIA_KEYBOARD_DOWNLOADABLE_LAYOUTS?=noPreloadDictRequired
# Enable user dictionary for built-in keyboard app by default
GAIA_KEYBOARD_ENABLE_USER_DICT?=1


ifeq ($(SYS),Darwin)
MD5SUM = md5 -r
SED_INPLACE_NO_SUFFIX = /usr/bin/sed -i ''
DOWNLOAD_CMD = /usr/bin/curl -OLsS
TAR_WILDCARDS = tar
else
MD5SUM = md5sum -b
SED_INPLACE_NO_SUFFIX = sed -i
DOWNLOAD_CMD = wget $(WGET_OPTS)
TAR_WILDCARDS = tar --wildcards
endif

# Test agent setup
TEST_COMMON=dev_apps/test-agent/common
ifeq ($(strip $(NODEJS)),)
  NODEJS := $(shell which node)
endif
ifeq ($(strip $(NODEJS)),)
  NODEJS := $(shell which nodejs)
endif

ifeq ($(strip $(NPM)),)
  NPM := $(shell which npm)
endif

TEST_AGENT_CONFIG="./dev_apps/test-agent/config.json"
TEST_AGENT_COVERAGE="./build/config/test-agent-coverage.json"

CAPABILITIES=$(GAIA_DIR)$(SEP)tests$(SEP)jsmarionette$(SEP)capabilities.json

#Marionette testing variables
#make sure we're python 2.7.x
ifeq ($(strip $(PYTHON_27)),)
PYTHON_27 := $(shell which python)
endif
PYTHON_FULL := $(wordlist 2,4,$(subst ., ,$(shell $(PYTHON_27) --version 2>&1)))
PYTHON_MAJOR := $(word 1,$(PYTHON_FULL))
PYTHON_MINOR := $(word 2,$(PYTHON_FULL))
MARIONETTE_HOST ?= localhost
MARIONETTE_PORT ?= 2828
TEST_DIRS ?= $(GAIA_DIR)/tests

PROFILE_DIR?=$(GAIA_DIR)$(SEP)$(PROFILE_FOLDER)
COREWEBAPPS_DIR?=$(PROFILE_DIR)

define BUILD_CONFIG
{ \
  "ADB" : "$(patsubst "%",%,$(ADB))", \
  "GAIA_DIR" : "$(GAIA_DIR)", \
  "PROFILE_DIR" : "$(PROFILE_DIR)", \
  "PROFILE_FOLDER" : "$(PROFILE_FOLDER)", \
  "COREWEBAPPS_DIR" : "$(COREWEBAPPS_DIR)", \
  "GAIA_SCHEME" : "$(SCHEME)", \
  "DEBUG" : "$(DEBUG)", \
  "DESKTOP" : "$(DESKTOP)", \
  "DEVICE_DEBUG" : "$(DEVICE_DEBUG)", \
  "NO_LOCK_SCREEN" : "$(NO_LOCK_SCREEN)", \
  "SCREEN_TIMEOUT" : "$(SCREEN_TIMEOUT)", \
  "SYSTEM" : "$(SYSTEM)", \
  "GAIA_PORT" : "$(GAIA_PORT)", \
  "GAIA_LOCALES_PATH" : "$(GAIA_LOCALES_PATH)", \
  "GAIA_INSTALL_PARENT" : "$(GAIA_INSTALL_PARENT)", \
  "LOCALES_FILE" : "$(subst \,\\,$(LOCALES_FILE))", \
  "GAIA_KEYBOARD_LAYOUTS" : "$(GAIA_KEYBOARD_LAYOUTS)", \
  "GAIA_KEYBOARD_DOWNLOADABLE_LAYOUTS" : "$(GAIA_KEYBOARD_DOWNLOADABLE_LAYOUTS)", \
  "GAIA_KEYBOARD_ENABLE_USER_DICT" : "$(GAIA_KEYBOARD_ENABLE_USER_DICT)", \
  "LOCALE_BASEDIR" : "$(subst \,\\,$(LOCALE_BASEDIR))", \
  "BUILD_APP_NAME" : "$(BUILD_APP_NAME)", \
  "PRODUCTION" : "$(PRODUCTION)", \
  "GAIA_OPTIMIZE" : "$(GAIA_OPTIMIZE)", \
  "GAIA_DEVICE_TYPE" : "$(GAIA_DEVICE_TYPE)", \
  "GAIA_DEV_PIXELS_PER_PX" : "$(GAIA_DEV_PIXELS_PER_PX)", \
  "DOGFOOD" : "$(DOGFOOD)", \
  "OFFICIAL" : "$(MOZILLA_OFFICIAL)", \
  "GAIA_DEFAULT_LOCALE" : "$(GAIA_DEFAULT_LOCALE)", \
  "GAIA_PRETRANSLATE" : "$(GAIA_PRETRANSLATE)", \
  "GAIA_CONCAT_LOCALES" : "$(GAIA_CONCAT_LOCALES)", \
  "GAIA_ENGINE" : "xpcshell", \
  "GAIA_DISTRIBUTION_DIR" : "$(GAIA_DISTRIBUTION_DIR)", \
  "GAIA_APPDIRS" : "$(GAIA_APPDIRS)", \
  "GAIA_ALLAPPDIRS" : "$(GAIA_ALLAPPDIRS)", \
  "GAIA_MEMORY_PROFILE" : "$(GAIA_MEMORY_PROFILE)", \
  "HARDWARE_COMPOSER" : "$(HARDWARE_COMPOSER)", \
  "NOFTU" : "$(NOFTU)", \
  "REMOTE_DEBUGGER" : "$(REMOTE_DEBUGGER)", \
  "TARGET_BUILD_VARIANT" : "$(TARGET_BUILD_VARIANT)", \
  "SETTINGS_PATH" : "$(subst \,\\,$(SETTINGS_PATH))", \
  "FTU_PING_URL" : "$(FTU_PING_URL)", \
  "KEYBOARD_LAYOUTS_PATH" : "$(KEYBOARD_LAYOUTS_PATH)", \
  "CONTACTS_IMPORT_SERVICES_PATH" : "$(CONTACTS_IMPORT_SERVICES_PATH)", \
  "EMAIL_SERVICES_PATH" : "$(EMAIL_SERVICES_PATH)", \
  "STAGE_DIR" : "$(STAGE_DIR)", \
  "GAIA_APP_TARGET" : "$(GAIA_APP_TARGET)", \
  "BUILD_DEBUG" : "$(BUILD_DEBUG)", \
  "VARIANT_PATH" : "$(VARIANT_PATH)", \
  "REBUILD" : "$(REBUILD)", \
  "P" : "$(P)", \
  "VERBOSE" : "$(VERBOSE)", \
  "PERF_LOGGING" : "$(PERF_LOGGING)", \
  "SHARE_PERF_USAGE" : "$(SHARE_PERF_USAGE)", \
  "DEFAULT_KEYBOAD_SYMBOLS_FONT" : "$(DEFAULT_KEYBOAD_SYMBOLS_FONT)", \
  "DEFAULT_GAIA_ICONS_FONT" : "$(DEFAULT_GAIA_ICONS_FONT)", \
  "RAPTOR" : "$(RAPTOR)", \
  "RAPTOR_TRANSFORM" : "$(RAPTOR_TRANSFORM)", \
  "RAPTOR_TRANSFORMER_PATH" : "$(RAPTOR_TRANSFORMER_PATH)", \
  "NGA_SERVICE_WORKERS" : "$(NGA_SERVICE_WORKERS)", \
  "FIREFOX_SYNC" : "$(FIREFOX_SYNC)", \
  "RUN_ON_NODE" : "$(RUN_ON_NODE)" \
}
endef

export BUILD_CONFIG

# Generate profile/
$(PROFILE_FOLDER): profile-dir build-app test-agent-config contacts extensions b2g_sdk .git/hooks/pre-commit
ifeq ($(BUILD_APP_NAME),*)
	@echo "Profile Ready: please run [b2g|firefox] -profile $(CURDIR)$(SEP)$(PROFILE_FOLDER)"
endif

$(STAGE_DIR):
	mkdir -p $@

LANG=POSIX # Avoiding sort order differences between OSes

.PHONY: build-app
build-app: app
	@$(call $(BUILD_RUNNER),update-webapps-json)

.PHONY: app
app: b2g_sdk preload-app profile-dir
	@$(call $(BUILD_RUNNER),app)

.PHONY: pre-app
pre-app: b2g_sdk profile-dir
	@$(call $(BUILD_RUNNER),pre-app)

# Keep old targets just for people/scripts still using it
.PHONY: post-manifest
post-manifest: app

.PHONY: copy-build-stage-data
copy-build-stage-data: app

.PHONY: webapp-optimize
webapp-optimize: app

.PHONY: webapp-zip
webapp-zip: app

.PHONY: preload-app
preload-app:
	$(call $(BUILD_RUNNER),preload,GAIA_DIR="$(GAIA_DIR)" GAIA_DISTRIBUTION_DIR="$(GAIA_DISTRIBUTION_DIR)")

# Get additional extensions
$(STAGE_DIR)/additional-extensions/downloaded.json: build/config/additional-extensions.json $(wildcard .build/config/custom-extensions.json)
ifeq ($(DESKTOP),1)
	@$(call $(BUILD_RUNNER),additional-extensions)
endif

profile-dir:
	@test -d $(PROFILE_FOLDER) || mkdir -p $(PROFILE_FOLDER)
ifeq ($(GAIA_DEVICE_TYPE), tv)
	@test -d $(PROFILE_FOLDER)/dummy || mkdir -p $(PROFILE_FOLDER)/dummy
	@cp $(GAIA_DIR)/build/config/tv/simulator/settings.json $(PROFILE_FOLDER)/dummy/
	@cp $(GAIA_DIR)/test_media/Movies/gizmo2.mp4 $(PROFILE_FOLDER)/dummy/
	@cp $(GAIA_DIR)/test_media/Movies/elephants-dream.webm $(PROFILE_FOLDER)/dummy/
endif

# Copy preload contacts to profile
contacts: profile-dir
ifeq ($(BUILD_APP_NAME),*)
ifdef CONTACTS_PATH
	@echo "Copying preload contacts to profile"
	@cp $(CONTACTS_PATH) $(PROFILE_FOLDER)
	@cp $(CONTACTS_PATH) $(PROFILE_FOLDER)/defaults/contacts.json
else
	@rm -f $(PROFILE_FOLDER)/contacts.json
endif
endif

# Create webapps
offline: app

# Create an empty reference workload
.PHONY: reference-workload-empty
reference-workload-empty:
	test_media/reference-workload/makeReferenceWorkload.sh empty

# Create a light reference workload
.PHONY: reference-workload-light
reference-workload-light:
	test_media/reference-workload/makeReferenceWorkload.sh light

# Create a medium reference workload
.PHONY: reference-workload-medium
reference-workload-medium:
	test_media/reference-workload/makeReferenceWorkload.sh medium

# Create a heavy reference workload
.PHONY: reference-workload-heavy
reference-workload-heavy:
	test_media/reference-workload/makeReferenceWorkload.sh heavy

# Create an extra heavy reference workload
.PHONY: reference-workload-x-heavy
reference-workload-x-heavy:
	test_media/reference-workload/makeReferenceWorkload.sh x-heavy

.PHONY: xpcshell_sdk xulrunner_sdk print-xulrunner-sdk
xpcshell_sdk:
	@echo $(XPCSHELLSDK)

xulrunner_sdk:
	@echo $(XULRUNNERSDK)

print-xulrunner-sdk:
	@echo "$(XULRUNNER_DIRECTORY)"

B2G_SDK_TMP := .b2g.tmp
.INTERMEDIATES: $(B2G_SDK_TMP)
.PHONY: b2g_sdk
b2g_sdk:
ifndef USE_LOCAL_XULRUNNER_SDK
ifneq ($(B2G_SDK_URL),$(shell test -d $(XULRUNNER_DIRECTORY) && cat $(B2G_SDK_URL_FILE) 2> /dev/null))
	rm -rf $(XULRUNNER_DIRECTORY)
	mkdir -p "$(XULRUNNER_DIRECTORY)"
	@echo "Downloading B2G SDK..."
	$(DOWNLOAD_CMD) "$(B2G_SDK_URL)"
ifeq ($(B2G_SDK_EXT),dmg)
# it's a nasty mac disk image
	@mkdir -p $(B2G_SDK_TMP)
	hdiutil attach $(B2G_SDK_FILE_NAME) -readonly -nobrowse -mount required -mountpoint $(B2G_SDK_TMP)
	cp -Rf $(B2G_SDK_TMP)/* "$(XULRUNNER_DIRECTORY)"
	ln -sf "$(XULRUNNER_DIRECTORY)/B2G.app/Contents/MacOS" "$(XULRUNNER_DIRECTORY)/b2g"
	umount $(B2G_SDK_TMP)
else ifeq ($(B2G_SDK_EXT),tar.bz2)
	tar xjf "$(B2G_SDK_FILE_NAME)" -C "$(XULRUNNER_DIRECTORY)"
else
	unzip -q "$(B2G_SDK_FILE_NAME)" -d "$(XULRUNNER_DIRECTORY)"
endif
	@rm -rf $(B2G_SDK_TMP) $(B2G_SDK_FILE_NAME)
	@echo $(B2G_SDK_URL) > $(B2G_SDK_URL_FILE)
endif # B2G SDK is up to date
endif # USE_LOCAL_XULRUNNER_SDK
	@test -f $(XPCSHELLSDK)

# Generate profile/prefs.js
preferences: profile-dir b2g_sdk
	@$(call $(BUILD_RUNNER),preferences)

# Generate profile/settings.json
settings: pre-app

# Generate $(PROFILE_FOLDER)/extensions
EXT_DIR=$(PROFILE_FOLDER)/extensions
extensions: $(STAGE_DIR)/additional-extensions/downloaded.json
ifeq ($(BUILD_APP_NAME),*)
	@rm -rf $(EXT_DIR)
	@mkdir -p $(EXT_DIR)
ifeq ($(DESKTOP),1)
	cp -r $(STAGE_DIR)/additional-extensions/* $(EXT_DIR)/
endif
ifeq ($(DEBUG),1)
	cp -r tools/extensions/{httpd,httpd@gaiamobile.org} $(EXT_DIR)/
endif
	@echo "Finished: Generating extensions"
endif


# this lists the programs we need in the Makefile and that are installed by npm

NPM_INSTALLED_PROGRAMS = node_modules/.bin/mozilla-download node_modules/.bin/jshint node_modules/.bin/mocha node_modules/.bin/eslint
$(NPM_INSTALLED_PROGRAMS): package.json node_modules

NODE_MODULES_REV=$(shell cat gaia_node_modules.revision)
# modules.tar and git-gaia-node-modules are the possible values for
# $(NODE_MODULES_SRC). See the node_modules target.
modules.tar: gaia_node_modules.revision $(NODE_MODULES_CACHEDIR)/$(NODE_MODULES_REV)
	-cp -f "$(NODE_MODULES_CACHEDIR)/$(NODE_MODULES_REV)" "$(NODE_MODULES_SRC)"

$(NODE_MODULES_CACHEDIR)/$(NODE_MODULES_REV): gaia_node_modules.revision
	@echo Downloading latest node_modules package. This may take several minutes...
	mkdir -p "$(NODE_MODULES_CACHEDIR)"
	-cd "$(NODE_MODULES_CACHEDIR)" && $(DOWNLOAD_CMD) https://github.com/mozilla-b2g/gaia-node-modules/tarball/$(NODE_MODULES_REV)

gaia.zip: $(DEFAULT_KEYBOAD_SYMBOLS_FONT) $(DEFAULT_GAIA_ICONS_FONT) $(PROFILE_FOLDER)
	@mkdir -p tmp/gaia tmp/gonk/system/fonts/hidden && cp -r $(PROFILE_FOLDER) tmp/gaia && \
	 cp $(DEFAULT_GAIA_ICONS_FONT) tmp/gonk/system/fonts/hidden && \
	 cp $(DEFAULT_KEYBOAD_SYMBOLS_FONT) tmp/gonk/system/fonts/hidden
	@cd tmp/ && zip -r -9 -u ../gaia.zip . && cd ../ && rm -r tmp/

git-gaia-node-modules: gaia_node_modules.revision
	if [ ! -d "$(NODE_MODULES_SRC)" ] ; then \
		git clone "$(NODE_MODULES_GIT_URL)" "$(NODE_MODULES_SRC)" ; \
	fi
	(cd "$(NODE_MODULES_SRC)" && git fetch && git reset --hard "$(NODE_MODULES_REV)" )

# npm-cache target is run when our node modules source is set to npm-cache
# which is a pre-built set of node modules for the current platform +
# node version present. The node modules selected for come from package.json.
#
# we run npm rebuild on marionette-js-runner to ensure that our python bits are
# setup properly (it's a postinstall script that runs only when we rebuild).
#
# calling npm rebuild ensures that local in tree modules get their dependencies
# installed. These are not part of the pre-built node modules at this time.
#
npm-cache:
	@echo "Using pre-deployed cache."
	$(NPM) install
	touch -c node_modules

node_modules: package.json
ifneq ($(strip $(NODEJS)),)
ifneq ($(NODE_VERSION),$(shell $(NODEJS) --version | awk -F. '{print $$1"."$$2}'))
	@printf '\033[0;33mPlease use $(NODE_VERSION) of nodejs or it may cause unexpected error.\033[0m\n'
endif
ifneq (1,$(shell expr `node --version | cut -c2` \>= $(NODE_MIN_VERSION)))
	@printf '\033[0;33mMinimum required version of nodejs v$(NODE_MIN_VERSION) not satisfied. Aborting. Install the required minimum version before continuing.\033[0m\n'
	exit 1
endif
ifneq ($(NPM_VERSION),$(shell $(NPM) --version | cut -d. -f1))
	@printf '\033[0;33mRequired version of npm v$(NPM_VERSION) not satisfied. Aborting. No other major versions are supported at this time.\033[0m\n'
	exit 1
endif
endif
	# TODO: Get rid of references to gaia-node-modules stuff.
	$(NPM) install
	$(NPM) run refresh

###############################################################################
# Tests                                                                       #
###############################################################################

MOZ_TESTS = "$(MOZ_OBJDIR)/_tests/testing/mochitest"
INJECTED_GAIA = "$(MOZ_TESTS)/browser/gaia"

TEST_PATH=gaia/tests/${TEST_FILE}

ifndef APPS
  ifdef APP
    APPS=$(APP)
  else
    APPS=template $(shell find apps -type d -name 'test' | sed -e 's|^apps/||' -e 's|/test$$||' | sort )
  endif
endif

mulet: node_modules
	DEBUG=* ./node_modules/.bin/mozilla-download \
	--product mulet \
	--branch mozilla-central \
	$(shell pwd)
	touch -c $@

.PHONY: test-integration
# $(PROFILE_FOLDER) should be `profile-test` when we do `make test-integration`.
test-integration: clean $(PROFILE_FOLDER) test-integration-test

# XXX Because bug-969215 is not finished, if we are going to run too many
# marionette tests for 30 times at the same time, we may easily get timeout.
#
# In this way, we decide to separate building process with running marionette
# tests so that we won't get into this problem.
#
# Remember to remove this target after bug-969215 is finished !
.PHONY: test-integration-test
test-integration-test: mulet node_modules
	TEST_MANIFEST=$(TEST_MANIFEST) $(NPM) run marionette -- --buildapp="$(BUILDAPP)" --reporter="$(REPORTER)" --marionette-capabilities="$(CAPABILITIES)"

.PHONY: jsmarionette-unit-tests
jsmarionette-unit-tests: mulet node_modules $(PROFILE_FOLDER) tests/jsmarionette/runner/marionette-js-runner/venv
	PROFILE_FOLDER=$(PROFILE_FOLDER) ./tests/jsmarionette/run_tests.js

tests/jsmarionette/runner/marionette-js-runner/venv:
	# Install virtualenv
	cd tests/jsmarionette/runner/marionette-js-runner && $(NPM) install
	# Still want to use $GAIA/node_modules
	rm -rf tests/jsmarionette/runner/marionette-js-runner/node_modules

.PHONY: raptor
raptor: node_modules
ifneq ($(APP),)
	GAIA_DISTRIBUTION_DIR=distros/raptor APP=$(APP) make install-gaia
else
	GAIA_DISTRIBUTION_DIR=distros/raptor make reset-gaia
endif

.PHONY: raptor-transformer
raptor-transformer: node_modules
ifeq ($(RAPTOR_TRANSFORM_RULES),)
	@(echo "Please ensure you specify the 'RAPTOR_TRANSFORM_RULES=<directory with the *.esp files>'" && exit 1)
endif
	@test -d $(RAPTOR_TRANSFORM_RULES) || (echo "Please ensure the '$(RAPTOR_TRANSFORM_RULES)' directory exists" && exit 1)
	RAPTOR_TRANSFORM=1 GAIA_DISTRIBUTION_DIR=distros/raptor make reset-gaia

.PHONY: tests
tests: app offline
	echo "Checking if the mozilla build has tests enabled..."
	test -d $(MOZ_TESTS) || (echo "Please ensure you don't have |ac_add_options --disable-tests| in your mozconfig." && exit 1)
	echo "Checking the injected Gaia..."
	test -L $(INJECTED_GAIA) || ln -s $(CURDIR) $(INJECTED_GAIA)
	TEST_PATH=$(TEST_PATH) make -C $(MOZ_OBJDIR) mochitest-browser-chrome EXTRA_TEST_ARGS="--browser-arg=\"\" --extra-profile-file=$(CURDIR)/$(PROFILE_FOLDER)/apps --extra-profile-file=$(CURDIR)/$(PROFILE_FOLDER)/user.js"

.PHONY: common-install
common-install:
	@test -x "$(NODEJS)" || (echo "Please Install NodeJS -- (use aptitude on linux or homebrew on osx)" && exit 1 )
	@test -x "$(NPM)" || (echo "Please install NPM (node package manager) -- http://npmjs.org/" && exit 1 )

.PHONY: update-common
update-common: common-install
	# common testing tools
	mkdir -p $(TEST_COMMON)/vendor/test-agent/
	rm -f $(TEST_COMMON)/vendor/test-agent/test-agent.js
	rm -f $(TEST_COMMON)/vendor/test-agent/test-agent.css
	cp node_modules/test-agent/test-agent.js $(TEST_COMMON)/vendor/test-agent/
	cp node_modules/test-agent/test-agent.css $(TEST_COMMON)/vendor/test-agent/

# Create the json config file
# for use with the test agent GUI
test-agent-config:
ifeq ($(BUILD_APP_NAME),*)
	@rm -f $(TEST_AGENT_CONFIG)
	@touch $(TEST_AGENT_CONFIG)
	@rm -f /tmp/test-agent-config;
	@# Build json array of all test files
	@for d in ${GAIA_ALLAPPDIRS}; \
	do \
		parent="`dirname $$d`"; \
		pathlen=`expr $${#parent} + 2`; \
		find -L "$$d" -name '*_test.js' -path '*/test/unit/*' | awk '{print substr($$0,'$${pathlen}')}' >> /tmp/test-agent-config; \
	done;
	@echo '{"tests": [' >> $(TEST_AGENT_CONFIG)
	@cat /tmp/test-agent-config |  \
		sed 's:\(.*\):"\1":' | \
		sed -e ':a' -e 'N' -e '$$!ba' -e 's/\n/,\
	/g' >> $(TEST_AGENT_CONFIG);
	@echo '  ]}' >> $(TEST_AGENT_CONFIG);
	@echo "Finished: test ui config file: $(TEST_AGENT_CONFIG)"
	@rm -f /tmp/test-agent-config
endif

# For test coverage report
COVERAGE?=0
ifeq ($(COVERAGE), 1)
TEST_ARGS=--coverage
endif
# Temp make file method until we can switch
# over everything in test
ifneq ($(strip $(APP)),)
APP_TEST_LIST=$(shell find -L $(GAIA_DIR)$(SEP)apps$(SEP)$(APP) $(GAIA_DIR)$(SEP)dev_apps$(SEP)$(APP) $(GAIA_DIR)$(SEP)tv_apps$(SEP)$(APP) -name '*_test.js' 2> /dev/null | grep '/test/unit/')
endif
.PHONY: test-agent-test
test-agent-test: node_modules
ifneq ($(strip $(APP)),)
	@echo 'Running tests for $(APP)';
	./node_modules/test-agent/bin/js-test-agent test $(TEST_ARGS) --server ws://localhost:$(TEST_AGENT_PORT) -t "$(TEST_AGENT_COVERAGE)" -m "://([a-zA-Z-_]+)\." --reporter $(REPORTER) $(APP_TEST_LIST)
else
	@echo 'Running all tests';
	./node_modules/test-agent/bin/js-test-agent test $(TEST_ARGS) --server ws://localhost:$(TEST_AGENT_PORT) -t "$(TEST_AGENT_COVERAGE)" -m "://([a-zA-Z-_]+)\." --reporter $(REPORTER)
endif

.PHONY: test-agent-server
test-agent-server: common-install node_modules
	./node_modules/test-agent/bin/js-test-agent server --port $(TEST_AGENT_PORT) -c ./build/config/test-agent-server.js -t "$(TEST_AGENT_COVERAGE)" -m "://([a-zA-Z-_]+)\." --http-path . --growl

.PHONY: marionette
marionette:
#need the profile
	test -d $(GAIA)/$(PROFILE_FOLDER) || $(MAKE) $(PROFILE_FOLDER)
ifneq ($(PYTHON_MAJOR), 2)
	@echo "Python 2.7.x is needed for the marionette client. You can set the PYTHON_27 variable to your python2.7 path." && exit 1
endif
ifneq ($(PYTHON_MINOR), 7)
	@echo "Python 2.7.x is needed for the marionette client. You can set the PYTHON_27 variable to your python2.7 path." && exit 1
endif
ifeq ($(strip $(MC_DIR)),)
	@echo "Please have the MC_DIR environment variable point to the top of your mozilla-central tree." && exit 1
endif
#if B2G_BIN is defined, we will run the b2g binary, otherwise, we assume an instance is running
ifneq ($(strip $(B2G_BIN)),)
	cd $(MC_DIR)/testing/marionette/client/marionette && \
	sh venv_test.sh $(PYTHON_27) --address=$(MARIONETTE_HOST):$(MARIONETTE_PORT) --b2gbin=$(B2G_BIN) $(TEST_DIRS)
else
	cd $(MC_DIR)/testing/marionette/client/marionette && \
	sh venv_test.sh $(PYTHON_27) --address=$(MARIONETTE_HOST):$(MARIONETTE_PORT) $(TEST_DIRS)
endif

###############################################################################
# Utils                                                                       #
###############################################################################

.PHONY: lint hint csslint eslint

# Lint apps
ifndef LINTED_FILES
ifdef APP
  JSHINTED_PATH = apps/$(APP)
else
  JSHINTED_PATH = apps shared build tests tv_apps
endif
endif

lint:
	$(MAKE) -k hint jsonlint csslint

JSHINT_ARGS := --reporter=build/jshint/reporter $(JSHINT_ARGS)

ifdef JSHINTRC
	JSHINT_ARGS := $(JSHINT_ARGS) --config $(JSHINTRC)
endif

ifdef VERBOSE
	JSHINT_ARGS := $(JSHINT_ARGS) --verbose
	VERBOSE=1
endif

hint: node_modules/.bin/jshint
	@echo Running jshint...
	@./node_modules/.bin/jshint $(JSHINT_ARGS) $(JSHINTED_PATH) $(LINTED_FILES) || (echo Please consult https://github.com/mozilla-b2g/gaia/tree/master/build/jshint/README.md to get some information about how to fix jshint issues. && exit 1)

eslint: node_modules/.bin/eslint
	sed 's/\s*#.*$$//' build/eslint/xfail.list | sort -u > build/eslint/xfail.list.tmp
	@echo Running eslint...
	@./node_modules/.bin/eslint --ignore-path build/eslint/xfail.list.tmp -f compact -c .eslintrc $(JSHINTED_PATH) $(LINTED_FILES)
	rm build/eslint/xfail.list.tmp

csslint: b2g_sdk node_modules
	@$(call run-node-command,csslint)

jsonlint: b2g_sdk
	@$(call run-node-command,jsonlint)

# Erase all the indexedDB databases on the phone, so apps have to rebuild them.
delete-databases:
	@echo 'Stopping b2g'
	@$(ADB) shell stop b2g
	@$(ADB) shell rm -r $(MSYS_FIX)/data/local/indexedDB/*
	@echo 'Starting b2g'
	@$(ADB) shell start b2g

# Take a screenshot of the device and put it in screenshot.png
screenshot:
	mkdir -p screenshotdata
	$(ADB) pull $(MSYS_FIX)/dev/graphics/fb0 screenshotdata/fb0
	dd bs=1920 count=800 if=screenshotdata/fb0 of=screenshotdata/fb0b
	ffmpeg -vframes 1 -vcodec rawvideo -f rawvideo -pix_fmt rgb32 -s 480x800 -i screenshotdata/fb0b -f image2 -vcodec png screenshot.png
	rm -rf screenshotdata

# Forward port to use the RIL daemon from the device
forward:
	$(ADB) shell touch $(MSYS_FIX)/data/local/rilproxyd
	$(ADB) shell killall rilproxy
	$(ADB) forward tcp:6200 localreserved:rilproxyd

# install-gaia is alias to build & push to device.
.PHONY: install-gaia
install-gaia: $(PROFILE_FOLDER) push

# If your gaia/ directory is a sub-directory of the B2G directory, then
# you should use:
#
#  BUILD_APP_NAME=app-name ./flash.sh gaia
#
# But if you're working on just gaia itself, and you already have B2G firmware
# on your phone, and you have adb in your path, then you can use the
# push target to update the gaia files and reboot b2g
.PHONY: push
push: b2g_sdk
	@$(call $(BUILD_RUNNER),push-to-device)

# Copy demo media to the sdcard.
# If we've got old style directories on the phone, rename them first.
install-media-samples:
	$(ADB) shell 'if test -d /sdcard/Pictures; then mv /sdcard/Pictures /sdcard/DCIM; fi'
	$(ADB) shell 'if test -d /sdcard/music; then mv /sdcard/music /sdcard/music.temp; mv /sdcard/music.temp /sdcard/Music; fi'
	$(ADB) shell 'if test -d /sdcard/videos; then mv /sdcard/videos /sdcard/Movies;	fi'

	$(ADB) push test_media/samples/DCIM $(MSYS_FIX)/sdcard/DCIM
	$(ADB) push test_media/samples/Movies $(MSYS_FIX)/sdcard/Movies
	$(ADB) push test_media/samples/Music $(MSYS_FIX)/sdcard/Music

install-test-media:
	$(ADB) push test_media/Pictures $(MSYS_FIX)/sdcard/DCIM
	$(ADB) push test_media/Movies $(MSYS_FIX)/sdcard/Movies
	$(ADB) push test_media/Music $(MSYS_FIX)/sdcard/Music

dialer-demo:
	@cp -R apps/contacts apps/dialer
	@rm apps/dialer/contacts/manifest*
	@mv apps/dialer/contacts/index.html apps/dialer/contacts/contacts.html
	@sed -i.bak 's/manifest.appcache/..\/manifest.appcache/g' apps/dialer/contacts/contacts.html
	@find apps/dialer/ -name '*.bak' -exec rm {} \;

demo: install-media-samples install-gaia

production: reset-gaia
dogfood: reset-gaia

# Remove everything and install a clean profile
reset-gaia: purge install-gaia install-default-data

# remove the memories and apps on the phone
purge:
	$(ADB) shell stop b2g
	@(for FILE in `$(ADB) shell ls $(MSYS_FIX)/data/local | tr -d '\r'`; \
	do \
		[ $$FILE = 'tmp' ] || $(ADB) shell rm -r $(MSYS_FIX)/data/local/$$FILE; \
	done);
	$(ADB) shell rm -r $(MSYS_FIX)/cache/*
	$(ADB) shell rm -r $(MSYS_FIX)/data/b2g/*
	$(ADB) shell rm -r $(MSYS_FIX)/data/local/apps
	$(ADB) remount
	$(ADB) shell rm -r $(MSYS_FIX)/system/b2g/apps
	$(ADB) shell 'if test -d $(MSYS_FIX)/persist/svoperapps; then rm -r $(MSYS_FIX)/persist/svoperapps; fi'

# push $(PROFILE_FOLDER)/settings.json and $(PROFILE_FOLDER)/contacts.json (if CONTACTS_PATH defined) to the phone
install-default-data: settings contacts app
	$(ADB) shell stop b2g
	$(ADB) remount
	$(ADB) push $(PROFILE_FOLDER)/settings.json $(MSYS_FIX)/system/b2g/defaults/settings.json
ifdef CONTACTS_PATH
	$(ADB) push $(PROFILE_FOLDER)/contacts.json $(MSYS_FIX)/system/b2g/defaults/contacts.json
else
	$(ADB) shell rm /system/b2g/defaults/contacts.json
endif
	$(ADB) shell start b2g

# clean out build products
clean:
	rm -rf profile profile-debug profile-test profile-gaia-test-b2g profile-gaia-test-firefox profile-raptor $(PROFILE_FOLDER) $(STAGE_DIR) docs minidumps

# clean out build products and tools
really-clean: clean
	rm -rf b2g-* .b2g-* b2g_sdk node_modules mulet firefox/ modules.tar js-marionette-env "$(NODE_MODULES_CACHEDIR)"

.git/hooks/pre-commit: tools/pre-commit
	test -d .git && cp tools/pre-commit .git/hooks/pre-commit && chmod +x .git/hooks/pre-commit || true

build-test-unit: b2g_sdk $(NPM_INSTALLED_PROGRAMS)
	@$(call run-node-command,build-test,TEST_TYPE=unit REPORTER=$(REPORTER) TRY_ENV=$(TRY_ENV) TEST_FILES="$(TEST_FILES)")

build-test-integration: b2g_sdk $(NPM_INSTALLED_PROGRAMS)
	@$(call run-node-command,build-test,TEST_TYPE=integration REPORTER=$(REPORTER) TRY_ENV=$(TRY_ENV) TEST_FILES="$(TEST_FILES)")

build-test-unit-coverage: $(NPM_INSTALLED_PROGRAMS)
	@$(call run-build-coverage,build/test/unit)

.PHONY: docs
docs: $(NPM_INSTALLED_PROGRAMS)
	gulp docs