bool tryParseAttributeReference(const StringPiece16& str, ResourceNameRef* outRef) {
    StringPiece16 trimmedStr(util::trimWhitespace(str));
    if (trimmedStr.empty()) {
        return false;
    }

    if (*trimmedStr.data() == u'?') {
        StringPiece16 package;
        StringPiece16 type;
        StringPiece16 entry;
        if (!extractResourceName(trimmedStr.substr(1, trimmedStr.size() - 1),
                                 &package, &type, &entry)) {
            return false;
        }

        if (!type.empty() && type != u"attr") {
            return false;
        }

        if (entry.empty()) {
            return false;
        }

        if (outRef) {
            outRef->package = package;
            outRef->type = ResourceType::kAttr;
            outRef->entry = entry;
        }
        return true;
    }
    return false;
}
예제 #2
0
static void promiseRejectHandlerInMainThread(v8::PromiseRejectMessage data)
{
    ASSERT(isMainThread());
    if (data.GetEvent() == v8::kPromiseHandlerAddedAfterReject) {
        rejectedPromisesOnMainThread().handlerAdded(data);
        return;
    }

    ASSERT(data.GetEvent() == v8::kPromiseRejectWithNoHandler);

    v8::Local<v8::Promise> promise = data.GetPromise();

    v8::Isolate* isolate = promise->GetIsolate();
    // There is no entered window during microtask callbacks from V8,
    // thus we call toDOMWindow() instead of enteredDOMWindow().
    LocalDOMWindow* window = currentDOMWindow(isolate);
    if (!window || !window->isCurrentlyDisplayedInFrame())
        return;

    v8::Local<v8::Value> exception = data.GetValue();
    if (V8DOMWrapper::isWrapper(isolate, exception)) {
        // Try to get the stack & location from a wrapped exception object (e.g. DOMException).
        ASSERT(exception->IsObject());
        v8::Local<v8::Object> obj = v8::Local<v8::Object>::Cast(exception);
        v8::Local<v8::Value> error = V8HiddenValue::getHiddenValue(isolate, obj, V8HiddenValue::error(isolate));
        if (!error.IsEmpty())
            exception = error;
    }

    int scriptId = 0;
    int lineNumber = 0;
    int columnNumber = 0;
    String resourceName;
    String errorMessage;
    RefPtrWillBeRawPtr<ScriptCallStack> callStack = nullptr;

    v8::Local<v8::Message> message = v8::Exception::CreateMessage(exception);
    if (!message.IsEmpty()) {
        if (v8Call(message->GetLineNumber(isolate->GetCurrentContext()), lineNumber)
            && v8Call(message->GetStartColumn(isolate->GetCurrentContext()), columnNumber))
            ++columnNumber;
        resourceName = extractResourceName(message, window->document());
        errorMessage = toCoreStringWithNullCheck(message->Get());
        callStack = extractCallStack(isolate, message, &scriptId);
    } else if (!exception.IsEmpty() && exception->IsInt32()) {
        // For Smi's the message would be empty.
        errorMessage = "Uncaught " + String::number(exception.As<v8::Integer>()->Value());
    }

    String messageForConsole = extractMessageForConsole(isolate, data.GetValue());
    if (!messageForConsole.isEmpty())
        errorMessage = "Uncaught " + messageForConsole;

    ScriptState* scriptState = ScriptState::current(isolate);
    rejectedPromisesOnMainThread().rejectedWithNoHandler(scriptState, data, errorMessage, resourceName, scriptId, lineNumber, columnNumber, callStack);
}
예제 #3
0
static void messageHandlerInMainThread(v8::Local<v8::Message> message, v8::Local<v8::Value> data)
{
    ASSERT(isMainThread());
    v8::Isolate* isolate = v8::Isolate::GetCurrent();
    // If called during context initialization, there will be no entered window.
    LocalDOMWindow* enteredWindow = enteredDOMWindow(isolate);
    if (!enteredWindow || !enteredWindow->isCurrentlyDisplayedInFrame())
        return;

    int scriptId = 0;
    RefPtrWillBeRawPtr<ScriptCallStack> callStack = extractCallStack(isolate, message, &scriptId);
    String resourceName = extractResourceName(message, enteredWindow->document());
    AccessControlStatus accessControlStatus = NotSharableCrossOrigin;
    if (message->IsOpaque())
        accessControlStatus = OpaqueResource;
    else if (message->IsSharedCrossOrigin())
        accessControlStatus = SharableCrossOrigin;

    ScriptState* scriptState = ScriptState::current(isolate);
    String errorMessage = toCoreStringWithNullCheck(message->Get());
    int lineNumber = 0;
    int columnNumber = 0;
    if (v8Call(message->GetLineNumber(scriptState->context()), lineNumber)
        && v8Call(message->GetStartColumn(scriptState->context()), columnNumber))
        ++columnNumber;
    RefPtrWillBeRawPtr<ErrorEvent> event = ErrorEvent::create(errorMessage, resourceName, lineNumber, columnNumber, &scriptState->world());

    String messageForConsole = extractMessageForConsole(isolate, data);
    if (!messageForConsole.isEmpty())
        event->setUnsanitizedMessage("Uncaught " + messageForConsole);

    // This method might be called while we're creating a new context. In this case, we
    // avoid storing the exception object, as we can't create a wrapper during context creation.
    // FIXME: Can we even get here during initialization now that we bail out when GetEntered returns an empty handle?
    LocalFrame* frame = enteredWindow->document()->frame();
    if (frame && frame->script().existingWindowProxy(scriptState->world())) {
        V8ErrorHandler::storeExceptionOnErrorEventWrapper(isolate, event.get(), data, scriptState->context()->Global());
    }

    if (scriptState->world().isPrivateScriptIsolatedWorld()) {
        // We allow a private script to dispatch error events even in a EventDispatchForbiddenScope scope.
        // Without having this ability, it's hard to debug the private script because syntax errors
        // in the private script are not reported to console (the private script just crashes silently).
        // Allowing error events in private scripts is safe because error events don't propagate to
        // other isolated worlds (which means that the error events won't fire any event listeners
        // in user's scripts).
        EventDispatchForbiddenScope::AllowUserAgentEvents allowUserAgentEvents;
        enteredWindow->document()->reportException(event.release(), scriptId, callStack, accessControlStatus);
    } else {
        enteredWindow->document()->reportException(event.release(), scriptId, callStack, accessControlStatus);
    }
}
/*
 * Style parent's are a bit different. We accept the following formats:
 *
 * @[[*]package:][style/]<entry>
 * ?[[*]package:]style/<entry>
 * <[*]package>:[style/]<entry>
 * [[*]package:style/]<entry>
 */
Maybe<Reference> parseStyleParentReference(const StringPiece16& str, std::string* outError) {
    if (str.empty()) {
        return {};
    }

    StringPiece16 name = str;

    bool hasLeadingIdentifiers = false;
    bool privateRef = false;

    // Skip over these identifiers. A style's parent is a normal reference.
    if (name.data()[0] == u'@' || name.data()[0] == u'?') {
        hasLeadingIdentifiers = true;
        name = name.substr(1, name.size() - 1);
    }

    if (name.data()[0] == u'*') {
        privateRef = true;
        name = name.substr(1, name.size() - 1);
    }

    ResourceNameRef ref;
    ref.type = ResourceType::kStyle;

    StringPiece16 typeStr;
    extractResourceName(name, &ref.package, &typeStr, &ref.entry);
    if (!typeStr.empty()) {
        // If we have a type, make sure it is a Style.
        const ResourceType* parsedType = parseResourceType(typeStr);
        if (!parsedType || *parsedType != ResourceType::kStyle) {
            std::stringstream err;
            err << "invalid resource type '" << typeStr << "' for parent of style";
            *outError = err.str();
            return {};
        }
    }

    if (!hasLeadingIdentifiers && ref.package.empty() && !typeStr.empty()) {
        std::stringstream err;
        err << "invalid parent reference '" << str << "'";
        *outError = err.str();
        return {};
    }

    Reference result(ref);
    result.privateReference = privateRef;
    return result;
}
bool parseResourceName(const StringPiece16& str, ResourceNameRef* outRef, bool* outPrivate) {
    if (str.empty()) {
        return false;
    }

    size_t offset = 0;
    bool priv = false;
    if (str.data()[0] == u'*') {
        priv = true;
        offset = 1;
    }

    StringPiece16 package;
    StringPiece16 type;
    StringPiece16 entry;
    if (!extractResourceName(str.substr(offset, str.size() - offset), &package, &type, &entry)) {
        return false;
    }

    const ResourceType* parsedType = parseResourceType(type);
    if (!parsedType) {
        return false;
    }

    if (entry.empty()) {
        return false;
    }

    if (outRef) {
        outRef->package = package;
        outRef->type = *parsedType;
        outRef->entry = entry;
    }

    if (outPrivate) {
        *outPrivate = priv;
    }
    return true;
}