docs: function $LocationProvider(){
    var hashPrefix = '',
        html5Mode = false;
  
    /**
     * @ngdoc property
     * @name ng.$locationProvider#hashPrefix
     * @methodOf ng.$locationProvider
     * @description
     * @param {string=} prefix Prefix for hash part (containing path and search)
     * @returns {*} current value if used as getter or itself (chaining) if used as setter
     */
    this.hashPrefix = function(prefix) {
      if (isDefined(prefix)) {
        hashPrefix = prefix;
        return this;
      } else {
        return hashPrefix;
      }
    };
  
    /**
     * @ngdoc property
     * @name ng.$locationProvider#html5Mode
     * @methodOf ng.$locationProvider
     * @description
     * @param {boolean=} mode Use HTML5 strategy if available.
     * @returns {*} current value if used as getter or itself (chaining) if used as setter
     */
    this.html5Mode = function(mode) {
      if (isDefined(mode)) {
        html5Mode = mode;
        return this;
      } else {
        return html5Mode;
      }
    };
  
    /**
     * @ngdoc event
     * @name ng.$location#$locationChangeStart
     * @eventOf ng.$location
     * @eventType broadcast on root scope
     * @description
     * Broadcasted before a URL will change. This change can be prevented by calling
     * `preventDefault` method of the event. See {@link ng.$rootScope.Scope#$on} for more
     * details about event object. Upon successful change
     * {@link ng.$location#$locationChangeSuccess $locationChangeSuccess} is fired.
     *
     * @param {Object} angularEvent Synthetic event object.
     * @param {string} newUrl New URL
     * @param {string=} oldUrl URL that was before it was changed.
     */
  
    /**
     * @ngdoc event
     * @name ng.$location#$locationChangeSuccess
     * @eventOf ng.$location
     * @eventType broadcast on root scope
     * @description
     * Broadcasted after a URL was changed.
     *
     * @param {Object} angularEvent Synthetic event object.
     * @param {string} newUrl New URL
     * @param {string=} oldUrl URL that was before it was changed.
     */
  
    this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement',
        function( $rootScope,   $browser,   $sniffer,   $rootElement) {
      var $location,
          LocationMode,
          baseHref = $browser.baseHref(), // if base[href] is undefined, it defaults to ''
          initialUrl = $browser.url(),
          appBase;
  
      if (html5Mode) {
        appBase = serverBase(initialUrl) + (baseHref || '/');
        LocationMode = $sniffer.history ? LocationHtml5Url : LocationHashbangInHtml5Url;
      } else {
        appBase = stripHash(initialUrl);
        LocationMode = LocationHashbangUrl;
      }
      $location = new LocationMode(appBase, '#' + hashPrefix);
      $location.$$parse($location.$$rewrite(initialUrl));
  
      $rootElement.on('click', function(event) {
        // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)
        // currently we open nice url link and redirect then
  
        if (event.ctrlKey || event.metaKey || event.which == 2) return;
  
        var elm = jqLite(event.target);
  
        // traverse the DOM up to find first A tag
        while (lowercase(elm[0].nodeName) !== 'a') {
          // ignore rewriting if no A tag (reached root element, or no parent - removed from document)
          if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;
        }
  
        var absHref = elm.prop('href');
        var rewrittenUrl = $location.$$rewrite(absHref);
  
        if (absHref && !elm.attr('target') && rewrittenUrl && !event.isDefaultPrevented()) {
          event.preventDefault();
          if (rewrittenUrl != $browser.url()) {
            // update location manually
            $location.$$parse(rewrittenUrl);
            $rootScope.$apply();
            // hack to work around FF6 bug 684208 when scenario runner clicks on links
            window.angular['ff-684208-preventDefault'] = true;
          }
        }
      });
  
  
      // rewrite hashbang url <> html5 url
      if ($location.absUrl() != initialUrl) {
        $browser.url($location.absUrl(), true);
      }
  
      // update $location when $browser url changes
      $browser.onUrlChange(function(newUrl) {
        if ($location.absUrl() != newUrl) {
          if ($rootScope.$broadcast('$locationChangeStart', newUrl,
                                    $location.absUrl()).defaultPrevented) {
            $browser.url($location.absUrl());
            return;
          }
          $rootScope.$evalAsync(function() {
            var oldUrl = $location.absUrl();
  
            $location.$$parse(newUrl);
            afterLocationChange(oldUrl);
          });
          if (!$rootScope.$$phase) $rootScope.$digest();
        }
      });
  
      // update browser
      var changeCounter = 0;
      $rootScope.$watch(function $locationWatch() {
        var oldUrl = $browser.url();
        var currentReplace = $location.$$replace;
  
        if (!changeCounter || oldUrl != $location.absUrl()) {
          changeCounter++;
          $rootScope.$evalAsync(function() {
            if ($rootScope.$broadcast('$locationChangeStart', $location.absUrl(), oldUrl).
                defaultPrevented) {
              $location.$$parse(oldUrl);
            } else {
              $browser.url($location.absUrl(), currentReplace);
              afterLocationChange(oldUrl);
            }
          });
        }
        $location.$$replace = false;
  
        return changeCounter;
      });
  
      return $location;
  
      function afterLocationChange(oldUrl) {
        $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl);
      }
  }];
  }