blob: 7202a3fd730ba4690db5c374992dc4429fdb1aa6 [file] [log] [blame]
/*
* Copyright 2015 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "cobalt/dom/location.h"
#include "base/bind.h"
#include "base/compiler_specific.h"
#include "base/logging.h"
namespace cobalt {
namespace dom {
Location::Location(const GURL& url, const base::Closure& hashchange_callback,
const base::Callback<void(const GURL&)>& navigation_callback,
const csp::SecurityCallback& security_callback)
: ALLOW_THIS_IN_INITIALIZER_LIST(url_utils_(
url, base::Bind(&Location::Replace, base::Unretained(this)))),
hashchange_callback_(hashchange_callback),
navigation_callback_(navigation_callback),
security_callback_(security_callback) {}
// Algorithm for Replace:
// https://www.w3.org/TR/html5/browsers.html#dom-location-replace
void Location::Replace(const std::string& url) {
// When the replace(url) method is invoked, the UA must resolve the argument,
// relative to the API base URL specified by the entry settings object, and if
// that is successful, navigate the browsing context to the specified url with
// replacement enabled and exceptions enabled.
GURL new_url = url_utils_.url().Resolve(url);
if (!new_url.is_valid()) {
DLOG(WARNING) << "New url is invalid, aborting the navigation.";
return;
}
const GURL& old_url = url_utils_.url();
// The following codes correspond to navigating the browsing context in HTML5.
// https://www.w3.org/TR/html5/browsers.html#navigate
// Since navigation in Cobalt always goes through Location interface, it is
// implemented here.
// If new URL is the same as old URL and they have hash, the navigation should
// be ignored.
if (new_url == old_url && new_url.has_ref()) {
return;
}
// Check new URL against security policy.
if (!security_callback_.is_null() &&
!security_callback_.Run(new_url, false /* did redirect */)) {
DLOG(WARNING) << "URL " << new_url
<< " is rejected by policy, aborting the navigation.";
return;
}
// Call either hashchange callback or navigation callback.
GURL::Replacements replacements;
replacements.ClearRef();
if (new_url.ReplaceComponents(replacements) ==
old_url.ReplaceComponents(replacements) &&
new_url.has_ref() && new_url.ref() != old_url.ref()) {
url_utils_.set_url(new_url);
if (!hashchange_callback_.is_null()) {
hashchange_callback_.Run();
}
} else {
if (!navigation_callback_.is_null()) {
navigation_callback_.Run(new_url);
}
}
}
void Location::Reload() {
if (!navigation_callback_.is_null()) {
LOG(INFO) << "Reloading URL: " << url();
navigation_callback_.Run(url());
}
}
} // namespace dom
} // namespace cobalt